package controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import dao.UserServiceInterface;
import entity.User;
import factory.ServiceFactory;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.JSONUtil;

import javax.naming.AuthenticationException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;

@WebServlet("/l")
public class LoginCtrl extends HttpServlet {
    private static final Logger logger = LoggerFactory.getLogger(LoginCtrl.class);
    private static final String SECRET_KEY = "XG23";
    private static final long TOKEN_EXPIRATION_TIME = 30 * 60 * 1000;
    private final UserServiceInterface userService = ServiceFactory.getService(UserServiceInterface.class, "UserService");
    private final JwtTokenGenerator jwtTokenGenerator = new JwtTokenGenerator(SECRET_KEY, TOKEN_EXPIRATION_TIME);
    private final ResponseHandler responseHandler = new ResponseHandler();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("text/html;charset=utf-8");
        try {
            User userToLogin = parseUserFromRequset(request);
            validateUserCredentials(userToLogin);
            String token = jwtTokenGenerator.generateToken(userToLogin.getId());
            responseHandler.sendSuccessRespon(response, token);
        } catch (IllegalArgumentException e) {
            logger.warn("无效请求参数: {}", e.getMessage());
            responseHandler.sendErrorResponse(response, e.getMessage(), 400);
        } catch (AuthenticationException e) {
            logger.warn("认证失败: {}", e.getMessage());
            responseHandler.sendErrorResponse(response, e.getMessage(), 401);
        } catch (SQLException e) {
            logger.error("数据库操作异常", e);
            responseHandler.sendErrorResponse(response, "数据库操作异常", 500);
        } catch (Exception e) {
            logger.error("系统异常", e);
            responseHandler.sendErrorResponse(response, "系统异常", 500);
        }
    }

    private User parseUserFromRequset(HttpServletRequest request) throws IOException {
        String userJson = JSONUtil.getJSON(request);
        User user = JSON.parseObject(userJson, User.class);

        if (user == null || user.getUsername() == null || user.getPassword() == null) {
            throw new IllegalArgumentException("请求参数不完整");
        }
        return user;
    }

    private void validateUserCredentials(User user) throws SQLException, AuthenticationException {
        userService.login(user);
        if (user.getId() == null) {
            throw new AuthenticationException("用户名不存在或密码错误");
        }
    }

    private static class JwtTokenGenerator {
        private final String secretKey;
        private final long expirationTime; // 1 hour

        public JwtTokenGenerator(String secretKey, long expirationTime) {
            this.secretKey = secretKey;
            this.expirationTime = expirationTime;
        }

        public String generateToken(Long userId) {
            return JWT.create()
                    .withSubject(String.valueOf(userId))
                    .withExpiresAt(new Date(System.currentTimeMillis() + expirationTime))
                    .sign(Algorithm.HMAC256(secretKey));
        }
    }

    private static class ResponseHandler {
        public void sendSuccessRespon(HttpServletResponse response, String token) throws IOException {
            JSONObject responseBody = new JSONObject();
            responseBody.put("message", "登录成功");
            responseBody.put("code", 200);
            responseBody.put("token", token);
            sendResponse(response, responseBody);
        }

        public void sendErrorResponse(HttpServletResponse response, String errorMsg, int statusCode) {
            try {
                JSONObject responseBody = new JSONObject();
                responseBody.put("message", errorMsg);
                responseBody.put("code", statusCode);
                response.setStatus(statusCode);
                sendResponse(response, responseBody);
            } catch (IOException e) {
                logger.error("发送错误响应失败", e);
            }
        }
    }

    private static void sendResponse(HttpServletResponse response, JSONObject responseBody) throws IOException {
        response.getWriter().println(JSON.toJSONString(responseBody));
    }
}    